<?php
namespace Hilaoyu\Utils;

define('IMG_PATH', './');
use Hilaoyu\Utils\Traits\ErrorsTrait;

class WechatJdk {
    use ErrorsTrait;

    private $appId;
    private $appSecret;
    private $fileExtension = '.jpg';
    public function __construct($appId, $appSecret) {
        $this->appId = $appId;
        $this->appSecret = $appSecret;
    }

    public function getSignPackage($client_url) {

        if(!($jsApiTicket = $this->getJsApiTicket())){
            return false;
        }

        $url = $client_url;
        $timestamp = time();
        $nonceStr = $this->createNonceStr();

        // 这里参数的顺序要按照 key 值 ASCII 码升序排序
        $string = "jsapi_ticket=$jsApiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";


        $signature = sha1($string);

        $signPackage = array(
            "appId"     => $this->appId,
            "nonceStr"  => $nonceStr,
            "timestamp" => $timestamp,
            "url"       => $url,
            "signature" => $signature,
            "rawString" => $string
        );

        return $signPackage;
    }

    private function createNonceStr($length = 16) {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    /**
     * 获取
     * @return mixed
     */
    private function getJsApiTicket() {
        // jsapi_ticket 应该全局存储与更新，以下代码以写入到文件中做示例
        $ticket = $this->getKeyCache("ticket");
        if($ticket){
            return $ticket;
        }

        if(! ($accessToken = $this->getAccessToken())){
            return false;
        }
        // 如果是企业号用以下 URL 获取 ticket
        // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
        $url    = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi";
        $res    = UtilHttp::RequestJson($url,['access_token'=>$accessToken],'get');

        if(!isset($res['ticket']) || empty($res['ticket'])){
            $error = '获取 ticket 出错';
            if(isset($res['errcode'])){
                $error .= ':' . $res['errcode'];
            }
            if(isset($res['errmsg'])){
                $error .= ':' . $res['errmsg'];
            }
            $this->setError($error);
            return false;
        }

        $ticket = $res['ticket'];
        $this->setKeyCache("ticket", $ticket,7000);

        return $ticket;
    }

    /**
     * 获取access_token
     * @return mixed
     */
    private function getAccessToken() {
        // access_token 应该全局存储与更新，以下代码以写入到文件中做示例
        $access_token = $this->getKeyCache("access_token");

        if($access_token){
            return $access_token;
        }

        // 如果是企业号用以下URL获取access_token
        //$url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appId&corpsecret=$this->appSecret";
        $url          = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";
        $res          = UtilHttp::RequestJson($url,['appid'=>$this->appId,'secret'=>$this->appSecret],'get');
        if(!isset($res['access_token']) || empty($res['access_token'])){
            $error = '获取 access_token 出错';
            if(isset($res['errcode'])){
                $error .= ':' . $res['errcode'];
            }
            if(isset($res['errmsg'])){
                $error .= ':' . $res['errmsg'];
            }
            $this->setError($error);
            return false;
        }

        $access_token =$res['access_token'];
        $this->setKeyCache("access_token",$access_token,7000);

        return $access_token;
    }


    /***
     * 从微信服务器下载图片
     * @param $url
     * @return array
     */
    private function downloadImage($url){
        $ch = curl_init($url);
        curl_setopt($ch,CURLOPT_HEADER,0);
        curl_setopt($ch,CURLOPT_NOBODY,0);//只去body头
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
        ob_clean();
        flush();
        $package  = curl_exec($ch);
        $httpinfo = curl_getinfo($ch);
        curl_close($ch);
        $imageAll = array_merge(array('header'=>$httpinfo),array('body'=>$package));

        return $imageAll;
    }
    /**
     * 获取全局变量缓存，redis版本或者php yac扩展版本
     * @param $key
     * @return array|string
     */
    public function getKeyCache($key) {

        $key = trim($key);

        if(!empty($key) && $cache = cache('wx_jdk_'.$key)){
            return $cache;
        }

        return '';


    }

    /**
     * 缓存全局变量，redis版本或者php yac扩展版本
     * @param $key
     * @param $content
     * @param $seconds
     * @return array
     */
    public function setKeyCache($key, $content,$seconds=7000) {

        $key = trim($key);

        if(!empty($key)){
            cache(['wx_jdk_'.$key => $content ], \Carbon\Carbon::now()->addSeconds($seconds));
            return (bool)$this->getKeyCache($key);
        }

        return false;


    }

    /**
     * 通过imageid获取图片
     * @param $img_id
     * @return mixed
     */
    public function getImage($img_id){
        //获取access_token
        $access_token = $this->getAccessToken();
        $url = 'https://api.weixin.qq.com/cgi-bin/media/get?access_token='.$access_token.'&media_id='.$img_id;
        //获取图片信息
        $img_http     = $this->downloadImage($url);
        $last_path    = '/'.date('Ym',time()).'/';
        $file_path    = IMG_PATH.$last_path;

        //如果目录不存在就创建目录，如果失败了就返回空
        if(!is_dir($file_path) && @mkdir($file_path,0777,true) === false){
           return '';
        }else{
            $tempFileType = $this->RandName();
            $file_name    = $file_path.$tempFileType;
            //保存成功返回路径
            if($this->saveImageFile($file_name,$img_http['body']) !==false){
                return $last_path.$tempFileType;
            }else{
                return '';
            }
        }

    }

    /**
     * 保存图片
     * @param $file_name
     * @param $file_content
     * @return int
     */
    private function saveImageFile($file_name,$file_content){
        return file_put_contents($file_name,$file_content);
    }

    /**
     * 自动生成文件名称
     * @return string
     */
    private function RandName(){
        $FileName	= time().rand(1000,9999);
        return $FileName.$this->fileExtension;
    }

    /**
     * @param string $uri 跳转到用户同意授权页
     * 调取之后如果成功微信会跳转到回调界面
     */
    public function auth($uri)
    {
        $appid = $this->appId;
        $redirect_uri = urlencode($uri);
        $url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' . $appid . '&redirect_uri=' . $redirect_uri . '&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect';

        header("Location:" . $url);
    }

    /**
     * 判断用户openid是否存在
     * @return bool
     * 获取用户 openid之前先调用此方法，判断是否需要重新获取用户openid
     */
    public function openid_has()
    {
        if (isset($_SESSION['wx_user']) && (!empty($_SESSION['wx_user']))) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * @param $code 用户code
     * @param $www_url 跳转url地址
     * 获取user_openid
     */
    public function get_openid($code,$www_url)
    {
        $appid  = $this->appId;
        $secret = $this->appSecret;
        $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $appid . '&secret=' . $secret . '&code=' . $code . '&grant_type=authorization_code';
        $result = file_get_contents($url);
        $result = json_decode($result, true);
        $urls = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" . $appid . "&grant_type=refresh_token&refresh_token=" . $result['refresh_token'] . "";
        $result = file_get_contents($urls);
        $result = json_decode($result, true);
        $urls = "https://api.weixin.qq.com/sns/userinfo?access_token=" . $result['access_token'] . "&openid=" . $result['openid'] . "&lang=zh_CN";
        $result = file_get_contents($urls);
        $result = json_decode($result, true);
        $openid = $result['openid'];
        if ($openid) {
            $_SESSION['wx_user'] = $result;
        }
        header("Location:" . $www_url);
    }

    /**
     * 获取user_openid
     * @param $code
     * @return bool|string
     */
    public function get_real_openid($code)
    {
        $appid  = $this->appId;
        $secret = $this->appSecret;
        $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $appid . '&secret=' . $secret . '&code=' . $code . '&grant_type=authorization_code';
        $result = UtilHttp::RequestJson($url,[],'get');
        //dd($result);
        /*$urls = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" . $appid . "&grant_type=refresh_token&refresh_token=" . $result['refresh_token'] . "";
        $result = file_get_contents($urls);
        $result = json_decode($result, true);
        $urls = "https://api.weixin.qq.com/sns/userinfo?access_token=" . $result['access_token'] . "&openid=" . $result['openid'] . "&lang=zh_CN";
        $result = file_get_contents($urls);
        $result = json_decode($result, true);*/
        if(!$result || !isset($result['openid'])){
            return false;
        }
        $openid = $result['openid'];
        if ($openid) {
            $_SESSION['wx_user'] = $result;
            return $openid;
        }else{
            return false;
        }
    }


    /**
     * 获取微信ACCESS_TOKEN
     **/
    public function get_access_token()
    {
        $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $this->appId . '&secret=' . $this->appSecret . '';
        $tmp = json_decode($this->curlGet($url), true);
        $access_token = $tmp['access_token'];
        return $access_token;
    }

    /**
     * 获取微信网页token,用户获取用户信息
     */
    public function get_access_token_web($code){
        $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid='.$this->appId.'&secret='.$this->appSecret.'&code='.$code.'&grant_type=authorization_code';
        return json_decode($this->curlGet($url), true);
    }

    /**
     * 获取用户基本信息
     **/
    public function get_user_info($code)
    {
        $access = $this->get_access_token_web($code);
        if(!empty($access['access_token']) || !empty($access['openid'])){
            $url = 'https://api.weixin.qq.com/sns/userinfo?access_token='.$access['access_token'].'&openid='.$access['openid'].'&lang=zh_CN';
            return json_decode($this->curlGet($url), true);
        }else{
            return array();
        }
    }

    /**
     * curl获取信息
     * @param $url
     * @return mixed
     */
    private function curlGet($url)
    {
        $ch = curl_init();
        $header = array("Accept-Charset: utf-8");
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
        curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        return curl_exec($ch);
    }

    /**
     * 检验access_tocken值网页版
     * @param $tocken
     * @param $openid
     * @return mixed
     */
    public function check_tocken($tocken,$openid){
        $url = 'https://api.weixin.qq.com/sns/auth?access_token='.$tocken.'&openid='.$openid;
        return json_decode($this->curlGet($url), true);
    }

}


